/**
 * @class 太阳系外围至本地泡对象实体
 * @author DuskyHuang 圣子
 * @description 本地泡是奥尔特云外围包裹整个太阳系的一个巨大空洞范围。
*/

import { Component, _decorator, Node, Vec3, Color, Camera } from 'cc';
import { core, utils } from 'cfw';
import { Res, SceneGraph, AxisRotation } from 'const';
import { CelestialLabel } from '../ui/items/celestial-label';
import { UIProxy, gizmos, ui } from 'proxies';
import { setLabelStyle } from 'helpers';
import { attenuate } from 'algorithms';
const { ccclass } = _decorator;

@ccclass('cocosmos.HelioLocalBubble')
export class HelioLocalBubble extends Component {

    protected onLoad(): void { this._init()._configure(); }

    protected onDisable(): void { this._freeLabels(); }

    public update(dt?: time.sec): void {
        const { showStructs, showTracks } = gizmos, { showCelNames } = ui;
        this._substructures.active = showStructs;
        this._solarDirection.active = showTracks;
        if (showCelNames && (showStructs || showTracks)) {
            this._claimLabels();
            for (const label of this._labels) {
                if (!label.target) continue;
                if (!label.target.activeInHierarchy) { label.alpha = 0; continue; }
                const name = label.target.name;
                const [, offset, mag] = LabelArgs[name];
                const ratio = label.target.worldScale.y * mag;
                const dist = ratio * offset.y;
                label.alpha = attenuate(dist, NameLabelAtt, false);
            }
        } else {
            this._freeLabels();
        }
    }

    private _init(): this {
        this._configs = core.res.getConfigItem<Record<string, groupConfigs>>(Res.Configs.SUBSTRUCTURES, "helios") ?? {};
        this._substructures = this.node.getChildByName('Substructures');
        this._solarDirection = this.node.getChildByName('Solar Direction');
        return this;
    }

    private _configure(): void {
        this._substructures.children.forEach(sub => {
            const config = this._configs[sub.name];
            if (notEmpty(config)) {
                const { pos: [x = 0, y = 0, z = 0], scale: [sx = 1, sy = 1, sz = 1], rotate: [rx = 0, ry = 0, rz = 0] } = config;
                sub.setScale(sx, sy, sz);
                sub.setPosition(x, y, z);
                sub.setRotationFromEuler(rx, ry, rz);
            }
        });
        this._substructures.forward = SOLAR_DIR;
        this._solarDirection.setPosition(v3a.set(SOLAR_DIR).multiplyScalar(-3.8));
        this._solarDirection.forward = SOLAR_DIR;
    }

    private _freeLabels(): void {
        if (notEmptyArr(this._labels)) this._labels.forEach(label => label.free());
        this._labels.length = 0;
    }

    private _claimLabels(): void {
        if (this._labels.length > 0) return;
        const camera = utils.findCamera(COSMOS, MAIN);
        this._substructures.children.forEach(sub => {
            this._claimLabel(sub.name, this._configs[sub.name].cname, sub, camera);
        });
        this._claimLabel('Solar Direction', '太阳系绕银心方向', this._solarDirection, camera);
    }

    private _claimLabel(name: string, cname: string, target: Node, camera: Camera): void {
        const [color, offset] = LabelArgs[name];
        const label = setLabelStyle(CelestialLabel.claim('struct', name.toLowerCase()), 'struct', 'helios');
        label.target = target;
        label.camera = camera;
        label.color = color;
        label.setOffset(offset);
        // label.string = cname;
        label.config = { en: name, cn: cname };
        this._labels.push(label);
    }

    private _substructures: Node;
    private _solarDirection: Node;
    protected _labels: CelestialLabel[] = [];
    protected _configs: Record<string, groupConfigs>;
}

const { COSMOS, Cameras: { MAIN } } = SceneGraph;
const { NameLabelAtt } = UIProxy;
const { SOLAR_DIR } = AxisRotation;
const v3a = new Vec3;

const LabelArgs: Record<string, [color: Color, offset: Vec3, magnify: num.ratio]> = {
    ['Terminal Shock']: [new Color(255, 191, 0, 255), new Vec3(0, 0.5, 0), 1],
    ['Helio Pause']: [new Color(255, 127, 0, 255), new Vec3(-0.1, 0.6, 0.075), 1],
    ['Bow Shock']: [new Color(63, 63, 255, 255), new Vec3(-0.2, 0.5, 0.15), 1],
    ['Hills Cloud']: [new Color(127, 191, 127, 255), new Vec3(0, 0.1, 0), 1],
    ['Oort Cloud']: [new Color(127, 127, 191, 255), new Vec3(0, 0.1, 0), 1],
    ['Solar Direction']: [new Color(255, 255, 0, 255), new Vec3(0, 0.08, 0), 10],
}